﻿import re
import struct
from core import *


class _GxComment:

    def __init__(self, line):
        self.type = line[1]
        self.comment = line[2:66] #

    def __repr__(self):
        return 'Comment: ;%s%s' % (self.type, self.comment)

    def code(self):
        comment_length = len(self.comment)
        if self.type == '*':
            comment_length = 1
        elif comment_length == 0:
            comment_length = 2
        return [0x80, comment_length] + map(ord, self.comment)

    def format(self, stream):
        stream.writecode(self.code())


def parse(line):
    return GxComment(line)


class GxCommentFile(object):
    def __init__(self, aliasSize=8, commentSize=32):
        self.aliasSize = aliasSize
        self.commentSize = commentSize
        self.comments = {}

    def getcomment(self, code):
        try:
            return self.comments[code]
        except KeyError:
            return None

    def getComment(self, name):
        code = deviceName2Code(name)
        return self.comments[code]

    def setComment(self, name, comment, alias=None):
        code = deviceName2Code(name)
        if type(comment) == tuple:
            alias, comment = comment
        if not alias:
            alias = " "*8
        self.comments[code] = alias, comment

    def load(self, filename, oldValueClear=True):
        self.path = filename
        self.f = BinaryReader(filename)

        # read head
        headsize = self.f.word()
        self.f.seek(-2, 1)
        self.header = self.f.read(headsize)

        commentstart = self.f.tell() + self.f.long()
        self.f.word() # 0으로 채워짐. 의미는 모름

        self.commentSize = self.f.byte()
        self.aliasSize   = self.f.byte()

        # read device code
        codes = []
        itemcount = self.f.word()
        for i in range(itemcount):
            code  = self.f.word()
            start = self.f.long()
            count = self.f.long()
            codes.append((code, start, count))

        if commentstart != self.f.tell():
            raise Exception("invalid device table")

        # read comment
        self.comments = {}
        for i in range(len(codes)):
            code, start, count = codes[i]
            for n in range(count):
                alias   = self.f.read(self.aliasSize)
                comment = self.f.read(self.commentSize)
                self.comments[(code, start+n)] = (alias, comment)
        self.f.close()

    def save(self, filename=None):
        if not filename:
            filename = self.path
            
        comments = self.comments.items()
        comments.sort()
        i = iter(comments)
        packedlist = []
        try:
            packed = []
            packed.append(i.next())
            while True:
                next = i.next()
                if (packed[-1][0][0] == next[0][0]) and (packed[-1][0][1] + 1) == next[0][1]:
                    packed.append(next)
                else:
                    packedlist.append(packed)
                    packed = [next]
        except StopIteration:
            if packed:
                packedlist.append(packed)

        f = BinaryWriter(filename)
        f.write(self.header)
        f.long(len(packedlist)*10+10)
        f.word(0)
        f.byte(self.commentSize)
        f.byte(self.aliasSize)
        f.word(len(packedlist))
        for packed in packedlist:
            first = packed[0][0]
            f.word(first[0])    # code
            f.long(first[1])    # start
            f.long(len(packed)) # count

        format = "%%-%ds%%-%ds" % (self.aliasSize, self.commentSize)
        for packed in packedlist:
            for code, comment in packed:
                alias   = comment[0][:self.aliasSize]
                comment = comment[1][:self.commentSize]
                f.write(format % (alias, comment))

        f.close()
